package com.fs.sys.web;

import com.alibaba.fastjson2.JSON;
import com.fs.common.AppConstants;
import com.fs.sys.bean.dto.AppDTO;
import com.fs.sys.bean.query.SysConfigQuery;
import com.fs.sys.entityservice.AppEntityService;
import com.fs.common.bean.UserContextHolder;
import com.fs.common.utils.TreeUtils;
import com.fs.sys.bean.dto.MenuDTO;
import com.fs.sys.bean.dto.SysConfigDTO;
import com.fs.sys.bean.dto.UserDTO;
import com.fs.sys.bean.resp.InitInfo;
import com.fs.sys.bean.resp.Route;
import com.fs.sys.service.UserAppService;
import com.fs.sys.entityservice.MenuEntityService;
import com.fs.sys.entityservice.SysConfigEntityService;
import com.fs.sys.entityservice.UserEntityService;
import jakarta.annotation.security.PermitAll;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 初始化控制器
 *
 * @author LiuQi 2024/10/4-9:27
 * @version V1.0
 **/
@RestController
@RequestMapping("/init")
public class InitController {
    @Autowired
    private UserEntityService userEntityService;

    @Autowired
    private MenuEntityService menuEntityService;

    @Autowired
    private SysConfigEntityService sysConfigEntityService;

    @Autowired
    private AppEntityService appEntityService;

    @Autowired
    private UserAppService userAppService;

    @Value("${app.multiple.enabled}")
    private Boolean multipleAppEnabled;

    @GetMapping("info")
    @PermitAll
    public InitInfo getInitInfo() {
        InitInfo initInfo = new InitInfo();
        String userId = UserContextHolder.getUserId().orElse("");
        String tenantId = UserContextHolder.getTenantId().orElse("");
        if (StringUtils.isNotBlank(userId)) {
            UserDTO userInfo = new UserDTO();
            if (!StringUtils.isEmpty(userId)) {
                userInfo = userEntityService.findById(userId).orElse(userInfo);
            }
            userInfo.setPassword(null);
            initInfo.setUserInfo(userInfo);
        }

        SysConfigQuery query = new SysConfigQuery();
        query.setCode("sysConfig");
        if (StringUtils.isNotBlank(tenantId)) {
            query.setTenantId(AppConstants.SUPER_TENANT);
        } else {
            query.setTenantId(tenantId);
        }
        SysConfigDTO config = sysConfigEntityService.findOne(query).orElse(null);
        if (null != config) {
            Map<String, Object> configs = JSON.parseObject(config.getValue());
            initInfo.setConfigInfo(configs);
        }

        // 获取路由信息
        if (StringUtils.isNotBlank(tenantId)) {
            // 单应用模式下，需要在此初始化菜单
            if (!multipleAppEnabled) {
                initInfo.setMenuTree(menuEntityService.getTree("sys", false, true));
            }

            List<AppDTO> apps = userAppService.findByUserCanVisit(tenantId, userId);

            if (!CollectionUtils.isEmpty(apps)) {
                List<String> appIds = apps.stream()
                        .map(AppDTO::getId).toList();
                Map<String, AppDTO> appMap = new HashMap<>(16);
                apps.forEach(app -> appMap.put(app.getId(), app));
                List<MenuDTO> menus = menuEntityService.queryBuilder()
                        .in("app_id", appIds)
                        .query();
                Map<String, List<MenuDTO>> appMenus = menus.stream()
                        .collect(Collectors.groupingBy(MenuDTO::getAppId));
                Map<String, List<Route>> routeMap = new HashMap<>(16);
                initInfo.setRoutes(routeMap);
                appMenus.forEach((appId, list) -> {
                    var app = appMap.get(appId);
                    List<MenuDTO> tree = TreeUtils.toTree(list);
                    List<Route> children = new ArrayList<>(16);
                    String appCode = app.getCode();
                    routeMap.put(appCode, children);

                    // 处理子路由
                    String prefix = multipleAppEnabled ? ("/" + appCode) : "";
                    TreeUtils.loopTree(tree, (item, parent) -> {
                        Route sub = new Route();
                        sub.setName(Optional.ofNullable(item.getPath()).map(p -> appCode + "/" + p).orElse(appCode));
                        if (null == item.getPath() || !item.getPath().startsWith("http")) {
                            if (StringUtils.isBlank(item.getPath())) {
                                sub.setPath(prefix);
                            } else {
                                sub.setPath(prefix + "/" + item.getPath());
                            }
                        } else {
                            sub.setPath(item.getPath());
                        }

                        if (StringUtils.isNotBlank(item.getCmp())) {
                            sub.setCmp("../views" + prefix + "/" + item.getCmp() + ".vue");
                        }
                        sub.setTitle(item.getName());

                        // 处理当前菜单子路由（未配置到菜单上的路由）
                        Map<String, Object> metadata = item.getMetadata();
                        if (null != metadata) {
                            List<Map<String, Object>> subRoutes = (List<Map<String, Object>>) metadata.get("subRoutes");
                            if (!CollectionUtils.isEmpty(subRoutes)) {
                                subRoutes.forEach(subItem -> {
                                            Route subRoute = new Route();
                                            subRoute.setPath(prefix + "/" + MapUtils.getString(subItem, "path"));
                                            subRoute.setCmp("../views" + prefix + "/" + MapUtils.getString(subItem, "cmp") + ".vue");
                                            subRoute.setTitle(MapUtils.getString(subItem, "title"));
                                            Map<String, Object> meta = new HashMap<>();
                                            meta.put("permPath", sub.getPath());
                                            subRoute.setMeta(meta);
                                            subRoute.setName(subRoute.getPath());
                                            children.add(subRoute);
                                        });
                            }
                        }

                        children.add(sub);
                    });
                });
            }
        }

        return initInfo;
    }

    /**
     * 获取转路由
     * @param menu 菜单
     * @return 路由
     */
    private Route menuToRoute(MenuDTO menu) {
        Route route = new Route();
        route.setName(menu.getPath());
        route.setPath(menu.getPath());

        if (StringUtils.isNotBlank(menu.getCmp())) {
            route.setCmp("../views/" + menu.getCmp() + ".vue");
        }
        route.setTitle(menu.getName());

        if (!CollectionUtils.isEmpty(menu.getChildren())) {
            route.setChildren(menu.getChildren().stream().map(this::menuToRoute).toList());
        }

        return route;
    }
}
